#pragma once
#include "types.h"
#include "param.h"
#include "riscv.h"
#include "spinlock.h"
#include "trapframe.h"

enum procstate {
  UNUSED = 0,
  USED,
  RUNNABLE,
  RUNNING,
  SLEEPING,
  ZOMBIE,
};

struct context {
  uint64 ra;
  uint64 sp;

  // Callee-saved 寄存器（RISC-V ABI）
  uint64 s0;
  uint64 s1;
  uint64 s2;
  uint64 s3;
  uint64 s4;
  uint64 s5;
  uint64 s6;
  uint64 s7;
  uint64 s8;
  uint64 s9;
  uint64 s10;
  uint64 s11;
};

struct proc {
  struct spinlock lock;

  // 生命周期
  enum procstate state;   // 进程状态
  void *chan;             // 睡眠等待通道
  int killed;             // 被杀标记
  int xstate;             // 退出码
  int pid;                // 进程ID

  // 亲缘关系
  struct proc *parent;

  // 执行环境（本实验为内核线程模型）
  uint64 kstack;          // 内核栈（内核虚拟地址，指向一页）
  struct context context; // 调度上下文
  struct trapframe *trapframe; // 预留：用户态切换使用（暂未启用）

  // 入口函数（内核线程）
  void (*entry)(void);

  // 文件描述符表
  struct file *ofile[NOFILE];  // 打开的文件

  // 调试信息
  char name[16];
};

struct cpu {
  struct context context; // scheduler 切换用上下文
  struct proc *proc;      // 当前在该 CPU 上运行的进程

    // 中断嵌套与状态（由 push_off/pop_off/acquire/release 维护）
  int noff;               // 关闭中断的嵌套深度
  int intena;             // 进入临界区前的中断使能状态
};

// 外部变量声明（在 proc.c 中定义）
extern struct proc proc[NPROC];
extern struct cpu cpus[NCPU];